import { Request, Response } from 'express';
import { stripe, stripeConfig } from '../config/stripe';
import Stripe from 'stripe';

/**
 * Get available payment methods based on currency
 * Some payment methods have currency restrictions
 */
const getPaymentMethodTypes = (currency: string): string[] => {
  const baseTypes = ['card']; // Card is always available
  
  // WeChat Pay: Supports CNY, USD, EUR, GBP, HKD, JPY, SGD, AUD, CAD
  if (['cny', 'usd', 'eur', 'gbp', 'hkd', 'jpy', 'sgd', 'aud', 'cad'].includes(currency.toLowerCase())) {
    baseTypes.push('wechat_pay');
  }
  
  // AliPay: Supports multiple currencies including USD, EUR, GBP, JPY, HKD, CNY
  if (['usd', 'eur', 'gbp', 'jpy', 'hkd', 'cny', 'aud', 'cad', 'sgd'].includes(currency.toLowerCase())) {
    baseTypes.push('alipay');
  }
  
  // US Bank Account (ACH): Only USD
  if (currency.toLowerCase() === 'usd') {
    baseTypes.push('us_bank_account');
  }
  
  // Customer Balance (for crypto/stablecoins): Multiple currencies
  if (['usd', 'eur', 'gbp'].includes(currency.toLowerCase())) {
    baseTypes.push('customer_balance');
  }
  
  return baseTypes;
};

/**
 * Create a Payment Intent for one-time payments
 * POST /api/payment/create-intent
 */
export const createPaymentIntent = async (req: Request, res: Response) => {
  try {
    const { amount, currency = stripeConfig.defaultCurrency, customerId, metadata } = req.body;

    // Validate amount
    if (!amount || amount <= 0) {
      return res.status(400).json({ error: 'Invalid amount' });
    }

    // Amount should already be in cents from frontend
    const amountInCents = Math.round(amount);

    // Create payment intent options
    // Use automatic_payment_methods to let Stripe enable all available methods for this account
    const paymentIntentOptions: Stripe.PaymentIntentCreateParams = {
      amount: amountInCents,
      currency,
      automatic_payment_methods: {
        enabled: true,
        allow_redirects: 'always', // Allow redirect-based payment methods like Alipay
      },
      metadata: metadata || {},
    };

    // Attach to customer if provided
    if (customerId) {
      paymentIntentOptions.customer = customerId;
    }

    const paymentIntent = await stripe.paymentIntents.create(paymentIntentOptions);

    res.json({
      clientSecret: paymentIntent.client_secret,
      paymentIntentId: paymentIntent.id,
    });
  } catch (error: any) {
    console.error('Error creating payment intent:', error);
    res.status(500).json({ 
      error: error.message || 'Failed to create payment intent' 
    });
  }
};

/**
 * Create a Setup Intent for saving payment methods
 * POST /api/payment/create-setup-intent
 */
export const createSetupIntent = async (req: Request, res: Response) => {
  try {
    const { customerId, metadata } = req.body;

    const setupIntentOptions: Stripe.SetupIntentCreateParams = {
      payment_method_types: [...stripeConfig.paymentMethodTypes],
      metadata: metadata || {},
    };

    // Attach to customer if provided
    if (customerId) {
      setupIntentOptions.customer = customerId;
    }

    const setupIntent = await stripe.setupIntents.create(setupIntentOptions);

    res.json({
      clientSecret: setupIntent.client_secret,
      setupIntentId: setupIntent.id,
    });
  } catch (error: any) {
    console.error('Error creating setup intent:', error);
    res.status(500).json({ 
      error: error.message || 'Failed to create setup intent' 
    });
  }
};

/**
 * List all payment methods for a customer
 * GET /api/payment/methods/:customerId
 */
export const listPaymentMethods = async (req: Request, res: Response) => {
  try {
    const { customerId } = req.params;

    if (!customerId) {
      return res.status(400).json({ error: 'Customer ID is required' });
    }

    const paymentMethods = await stripe.paymentMethods.list({
      customer: customerId,
      type: 'card',
    });

    // Get customer to check default payment method
    const customer = await stripe.customers.retrieve(customerId) as Stripe.Customer;
    const defaultPaymentMethodId = customer.invoice_settings?.default_payment_method as string | undefined;

    // Format payment methods
    const formattedMethods = paymentMethods.data.map(pm => ({
      id: pm.id,
      brand: pm.card?.brand,
      last4: pm.card?.last4,
      expMonth: pm.card?.exp_month,
      expYear: pm.card?.exp_year,
      isDefault: pm.id === defaultPaymentMethodId,
    }));

    res.json({ methods: formattedMethods });
  } catch (error: any) {
    console.error('Error listing payment methods:', error);
    res.status(500).json({ 
      error: error.message || 'Failed to list payment methods' 
    });
  }
};

/**
 * Attach a payment method to a customer
 * POST /api/payment/methods/attach
 */
export const attachPaymentMethod = async (req: Request, res: Response) => {
  try {
    const { paymentMethodId, customerId, setAsDefault = false } = req.body;

    if (!paymentMethodId || !customerId) {
      return res.status(400).json({ error: 'Payment method ID and customer ID are required' });
    }

    // Attach payment method to customer
    const paymentMethod = await stripe.paymentMethods.attach(paymentMethodId, {
      customer: customerId,
    });

    // Set as default if requested
    if (setAsDefault) {
      await stripe.customers.update(customerId, {
        invoice_settings: {
          default_payment_method: paymentMethodId,
        },
      });
    }

    res.json({
      success: true,
      paymentMethod: {
        id: paymentMethod.id,
        brand: paymentMethod.card?.brand,
        last4: paymentMethod.card?.last4,
        expMonth: paymentMethod.card?.exp_month,
        expYear: paymentMethod.card?.exp_year,
      },
    });
  } catch (error: any) {
    console.error('Error attaching payment method:', error);
    res.status(500).json({ 
      error: error.message || 'Failed to attach payment method' 
    });
  }
};

/**
 * Detach (delete) a payment method
 * DELETE /api/payment/methods/:paymentMethodId
 */
export const detachPaymentMethod = async (req: Request, res: Response) => {
  try {
    const { paymentMethodId } = req.params;

    if (!paymentMethodId) {
      return res.status(400).json({ error: 'Payment method ID is required' });
    }

    await stripe.paymentMethods.detach(paymentMethodId);

    res.json({ success: true, message: 'Payment method removed' });
  } catch (error: any) {
    console.error('Error detaching payment method:', error);
    res.status(500).json({ 
      error: error.message || 'Failed to detach payment method' 
    });
  }
};

/**
 * Set a payment method as default for a customer
 * POST /api/payment/methods/set-default
 */
export const setDefaultPaymentMethod = async (req: Request, res: Response) => {
  try {
    const { paymentMethodId, customerId } = req.body;

    if (!paymentMethodId || !customerId) {
      return res.status(400).json({ error: 'Payment method ID and customer ID are required' });
    }

    await stripe.customers.update(customerId, {
      invoice_settings: {
        default_payment_method: paymentMethodId,
      },
    });

    res.json({ success: true, message: 'Default payment method updated' });
  } catch (error: any) {
    console.error('Error setting default payment method:', error);
    res.status(500).json({ 
      error: error.message || 'Failed to set default payment method' 
    });
  }
};

/**
 * Create a Stripe customer
 * POST /api/payment/create-customer
 */
export const createCustomer = async (req: Request, res: Response) => {
  try {
    const { email, name, metadata } = req.body;

    if (!email) {
      return res.status(400).json({ error: 'Email is required' });
    }

    const customer = await stripe.customers.create({
      email,
      name,
      metadata: metadata || {},
    });

    res.json({
      customerId: customer.id,
      email: customer.email,
      name: customer.name,
    });
  } catch (error: any) {
    console.error('Error creating customer:', error);
    res.status(500).json({ 
      error: error.message || 'Failed to create customer' 
    });
  }
};
